package com.estar.integaration.DS;

import com.estar.integaration.Util.Util;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;

import java.util.*;

/**
 * Author: YJL
 * Date: 2021/12/30 9:02
 **/
@Data
@AllArgsConstructor
@NoArgsConstructor
public class DirectDFS {
  Graph graph;//图的顶点个数，边个数，邻接矩阵

  HashMap<String,Integer> cMaterialGroupHashMap;

  HashMap<String,String> materialTrackHashMap = new HashMap<>();

  LinkedList<LinkedList<Integer>> linkedListVertices = null;//邻接矩阵

  public HashMap<String, String> getMaterialTrackHashMap() {
    return materialTrackHashMap;
  }

  public void setcMaterialGroupHashMap(HashMap<String, Integer> cMaterialGroupHashMap) {
    this.cMaterialGroupHashMap = cMaterialGroupHashMap;
  }

  public DirectDFS(Graph graph,HashMap<String,Integer> cMaterialGroupHashMap) {
    this.cMaterialGroupHashMap = cMaterialGroupHashMap;
    this.graph = graph;
  }

  //返回第一个邻接顶点的序号(一行里面找第一个1)
  public Integer firstAdjoinVexIndex(Graph g,int v){
    for(int i = 0; i < g.getVertexNum() ; i++){
      if(g.getVertices()[v][i] == 1)
        return i;
    }
    return -1;
  }

  //返回w序号之后的下一个邻接点序号
  public Integer nextAdjoinVexIndex(Graph g,int v,int w){
    for(int i = w+1; i < g.getVertexNum();i++){
      if(g.getVertices()[v][i] == 1){
        return i;
      }
    }
    return -1;
  }

  public void DFS(Graph g,int i){
    Integer group = cMaterialGroupHashMap.get(g.getVertexs()[i].getData());
    if(group == null){
      group = -1;
    }
    System.out.printf(g.getVertexs()[i].getData() + group  + "--->");
    g.getVertexs()[i].visit();
    for(int w = firstAdjoinVexIndex(g,i); w > 0; w = nextAdjoinVexIndex(g,i,w)){
      if(!g.getVertexs()[i].isVisited()){
        DFS(g,w);
      }
    }
  }

  /**
   *
   * @param g 图
   * @param cur 当前到哪一行
   * @param
   */
  //遍历matrix
  public void DFSMa(Graph g, int cur){ //cur是行(竖) j列(横)
    /**
     * //全是0说明已经到达终点了
      if(Util.isAllZeroArray(g.getVertices()[cur])){
        allList.add(new ArrayList<>(thisPath));
        return;
      }**/
      Integer[] nextParents = g.getVertices()[cur];
      //到达终点,收集list
      if(nextParents.length == 0){
        list.add(new ArrayList<Integer>(stack));
        return;
      }

      for(int next : nextParents){//读出全部父并且输出
        stack.add(next);
        DFSMa(g,next);
        stack.pollLast();
      }
  }

  LinkedList<Integer> nextParents = new LinkedList<>();

  public void DFSLinkedListMa(Graph g,int cur){//cur是竖着的那排序号

    nextParents = linkedListVertices.get(cur);
    //到达终点,收集list
    if(nextParents.size() == 0){
      try {
        list.add(new ArrayList<Integer>(stack));
        System.out.println(list.size());
      }catch (StackOverflowError e){
        System.out.println("内存溢出---------------数组大小"+list.size());
        e.printStackTrace();
      }
      return;
    }

    for(Integer next : nextParents){//读出全部父并且输出
      if(next == cur)
        continue;//自己形成自己 肯定错误(内存泄露)
      stack.add(next);
      DFSLinkedListMa(g,next);
      stack.pollLast();
    }
  }

  public void DFSTransfer(Graph g){
    for(int i = 0; i < g.getVertexNum();i++){
      g.getVertexs()[i].unVisit();
    }
    for(int i = 0; i < g.getVertexNum();i++){
      if(!g.getVertexs()[i].isVisited()){
        DFS(g,i);
      }
    }
    System.out.println("");
  }

  //遍历找
  List<List<Integer>> list = new ArrayList<>();
  Deque<Integer> stack = new ArrayDeque<>();
  public List<List<Integer>> DFSRun(Graph g){
    linkedListVertices = g.getLinkedListVertices();
    for(int i = 0; i < g.getVertexNum();i++){//这边一直在跑
      stack.add(i);
//      DFSMa(g,i);
      DFSLinkedListMa(g,i);
      stack = new ArrayDeque<>();
    }
    printDoubleArray(list); //输出
    return list;
  }

  private void printDoubleArray(List<List<Integer>> aList){
    StringBuilder sb = new StringBuilder();
    for(int k = 0; k < aList.size();k++){
      List<Integer> tmpList = aList.get(k);
      for(int l = 0; l < tmpList.size();l++){
        System.out.print(this.graph.getVertexs()[tmpList.get(l)].getData());
        String s = this.graph.getVertexs()[tmpList.get(l)].getData();
        if(s == null){
          System.out.println("图中数据为空");
          continue;
        }
        Integer group = -1;

        if(cMaterialGroupHashMap.containsKey(s)){
          group = cMaterialGroupHashMap.get(s);
        }
        if(group == null) group = -1;
        System.out.print( "[" + group + "]");
        sb.append(this.graph.getVertexs()[tmpList.get(l)].getData());
        sb.append("[" + String.valueOf(group) + "]");
        if(l != tmpList.size() - 1){
          System.out.print("--->");
          sb.append("--->");
        }
      }
      System.out.println("");
    }
  }

  /**
   * 从物料关系index的List得到物料号关系的List
   * @param materialIndexRS
   * @param vertices
   * @return
   */
  public List<List<String>> getMaterialCodeRelationShipFromMaterialCodeIndex(List<List<Integer>> materialIndexRS,Vertex[] vertices){
    List<List<String>> materialCodeRSList = new LinkedList<>();
    for(int i = 0; i < materialIndexRS.size(); i++){
      List<String> materialCodeRS = new LinkedList<>();
      for(int j = 0; j < materialIndexRS.get(i).size(); j++){
        Integer index = materialIndexRS.get(i).get(j);
        materialCodeRS.add(vertices[index].getData());
      }
      materialCodeRSList.add(materialCodeRS);
    }
    return materialCodeRSList;
  }


}
